// 协议
#pragma once

#include <iostream>
#include <vector>
#include <jsoncpp/json/json.h>
using namespace std;

#define DATA_SEP " " // 序列化间隔
#define DATA_SEP_LEN strlen(DATA_SEP)
#define HEADERS_SEP "\r\n"
#define HEADERS_SEP_LEN strlen(HEADERS_SEP)

//#define MYSELF 1 //是否用自己写的序列化与反序列化

//"数据长度""\r\n""数据""\r\n"
// 增加报头
string AddHeaders(const string &str)
{
    string ret;
    ret += to_string(str.size());
    ret += HEADERS_SEP;
    ret += str;
    ret += HEADERS_SEP;
    return ret;
}

// 去除报头
string SubHeaders(const string &str, int len)
{
    string ret = str.substr(str.size() - HEADERS_SEP_LEN - len, len);
    return ret;
}

// 将操作数和操作符分割进res
static bool StrSplit(const string &str, vector<string> &res)
{
    int start = 0;
    while (start < str.size())
    {
        int pos = str.find(DATA_SEP, start);
        if (pos == string::npos)
        {
            break;
        }
        res.push_back(str.substr(start, pos - start));
        start = pos + DATA_SEP_LEN;
    }

    if (start < str.size())
    {
        res.push_back(str.substr(start));
    }

    return true;
}

//从流中读取一条完整的数据--"7"\r\n"10 + 20"\r\n
int ReadPackage(int sock, string& inbuffer, string& package)
{
    char buff[1024];
    int n = recv(sock, buff, sizeof(buff) - 1, 0);
    if(n <= 0)
    {
        return -1; //1 表示读取失败
    }

    buff[n] = '\0';
    inbuffer += buff;
    int pos = inbuffer.find(HEADERS_SEP);
    //读取到了数据,但是数据并不完整
    if(pos == string::npos)
    {
        return 0; //表示读取到了数据,但是数据并不完整
    }
    string data_str = inbuffer.substr(0, pos);
    int data_len = stoi(data_str); //截取出有效荷载的长度
    int complete_len = data_str.size() + data_len + 2 * HEADERS_SEP_LEN; //读取到的完整数据的长度
    if(inbuffer.size() < complete_len)
    {
        return 0; //表示读取到了数据,但是数据并不完整
    }
    package = inbuffer.substr(0, complete_len);
    inbuffer.clear();

    return data_len;
}

// 请求
class Request
{
public:
    Request()
    {
    }

    Request(int x, int y, int op) : _x(x), _y(y), _op(op)
    {
    }

    // 序列化: x op y (操作数与操作符之间以空格间隔)
    // 序列化 -- 结构体->string
    bool Serialize(string &str)
    {
        str.clear();
#ifdef MYSELF
        str += to_string(_x) + DATA_SEP + _op + DATA_SEP + to_string(_y);
#else
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["op"] = _op;

        Json::FastWriter writer;
        str = writer.write(root);

#endif
        return true;
    }

    // 反序列化 -- string->结构体
    bool Deserialize(const string &str)
    {
#ifdef MYSELF
        vector<string> res; // 存储操作数与操作符
        StrSplit(str, res);

        if (res.size() != 3)
        {
            return false;
        }
        if (res[1].size() != 1)
        {
            return false;
        }
        _x = stoi(res[0]);
        _op = res[1][0];
        _y = stoi(res[2]);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(str, root);

        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _op = root["op"].asInt();
        
#endif
        return true;
    }

    ~Request()
    {
    }

public:
    int _x;   // 左操作数
    int _y;   // 右操作数
    char _op; // 操作符
};

// 回应
class Response
{
public:
    Response()
    {
    }
    Response(int result, int code) : _result(result), _code(code)
    {
    }

    // 序列化: result code (操作数与操作符之间以空格间隔)
    // 序列化 -- 结构体->string
    bool Serialize(string &str)
    {
        str.clear();
#ifdef MYSELF
        str += to_string(_result) + DATA_SEP + to_string(_code);
#else
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        str = writer.write(root);
#endif
        return true;
    }

    // 反序列化 -- string->结构体
    bool Deserialize(const string &str)
    {
#ifdef MYSELF
        vector<string> res; // 存储操作数与操作符
        StrSplit(str, res);

        if (res.size() != 2)
        {
            return false;
        }

        _result = stoi(res[0]);
        _code = stoi(res[1]);
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(str, root);

        _result = root["result"].asInt();
        _code = root["code"].asInt();
#endif
        return true;
    }

    ~Response()
    {
    }

public:
    int _result; // 结果
    int _code;   // 退出码, 0表示正常, 其他诸如1、2、3...为异常
};